package com.web.kdl.service.Minio;

import com.web.kdl.common.result.CommonResult;
import com.web.kdl.common.result.MessageConstants;
import com.web.kdl.config.Minio.MinioProperties;
import com.web.kdl.pojo.Vo.SvgVo;
import com.web.kdl.pojo.dto.TableDto;
import com.web.kdl.util.FileTypeConstants;
import io.minio.*;
import io.minio.messages.Item;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.web.multipart.MultipartFile;
import org.thymeleaf.util.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.*;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @Author： shulibin
 * @Date： 2025/9/3 10:54
 * @Describe： MinioService
 */
@Slf4j
@Component
public class MinioService {
    @Autowired
    private MinioClient minioClient;
    @Autowired
    private MinioProperties minioProperties;
    @Autowired
    private FilesService filesService;
    @Value("${file.HMI-path}")
    private String HmiPath;
    @Value("${kdl.baseUrl}")
    private String baseUrl;

    private static final String ImageName="background";

    /**
     * 站点的文件
     *  path:url/site/siteName.HMI
     * 飞轮的文件
     *  path:url/siteName/flywheelName.HMI
     */
    public CommonResult createSite(String siteName) throws IOException {
        return createFile(siteName,null,null);
    }

    public CommonResult createFlyWheelFile(TableDto dto) throws IOException {
        return createFile(dto.getSiteName(),dto.getMatrixName(),dto.getFlywheelName());
    }

    /**
     * 创建本地HMI文件
     * @param siteName
     * @param flywheelName
     * @return
     * @throws IOException
     */
    public CommonResult createFile(String siteName,String matrixName, String flywheelName) throws IOException {
        try {
            // 参数校验
            Objects.requireNonNull(siteName, "siteName不能为空");

            // 构建文件路径
            Path baseDir = Paths.get(HmiPath);
            Path fileDir = (flywheelName == null || flywheelName.isEmpty())
                    ? baseDir.resolve(siteName)
                    : baseDir.resolve(siteName).resolve(matrixName);

            String fileName = (flywheelName == null || flywheelName.isEmpty())
                    ? siteName + FileTypeConstants.RT1000_FILE_TYPE
                    : flywheelName + FileTypeConstants.RT1000_FILE_TYPE;

            Path filePath = fileDir.resolve(fileName);
            // 创建目录（如果不存在）
            if (!Files.exists(fileDir)) {
                Files.createDirectories(fileDir);
                log.info("创建目录: {}", fileDir);
            }
            // 检查文件是否已存在
            if (Files.exists(filePath)) {
                log.warn("文件已存在: {}", filePath);
                return CommonResult.success(MessageConstants.FILE_EXISTS,filePath.toString());
            }
            // 创建文件
            Files.createFile(filePath);
            log.info("文件创建成功: {}", filePath);
            return CommonResult.success(MessageConstants.FILE_CREATE_SUCCESS, filePath.toString());
        } catch (IOException e) {
            log.error("创建文件失败 - siteName: {}, flywheelName: {}", siteName, flywheelName, e);
            throw new IOException("创建文件失败: " + e.getMessage(), e);
        }
    }

    /**
     * 上传 本地文件至minio保存
     * @param dto
     * @return
     */
    @NotNull
    public String uploadFile(TableDto dto,MultipartFile file){
        String siteName = dto.getSiteName();
        // 判断当前文件是否存在
        // 1.存在则返回url
        // 2.不存在则创建文件
        try {
            // 确保存储桶存在
            bucketExists(minioProperties.getBuckets().get("site").getName());
            // 文件名
            String fileName;

            if (dto.getFlywheelName()!=null){
                fileName = buildFileName(siteName,dto.getMatrixName(), dto.getFlywheelName());
            }else{
                fileName = buildFileName(siteName,null, null);
            }
            long fileSize = file.getSize();
            String contentType = file.getContentType();
            InputStream inputStream = file.getInputStream();
            if (contentType == null) {
                contentType = "application/octet-stream";
            }

            // 上传文件到MinIO
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(minioProperties.getBuckets().get("site").getName())
                    .object(fileName)
                    .stream(inputStream, fileSize, -1)
                    .contentType(contentType)
                    .build());

            // 关闭输入流
            if (inputStream != null) {
                inputStream.close();
            }
            // 构建访问URL并更新数据库
            String url = minioProperties.getUrl() + "/" + fileName;
            filesService.addOrUpdate(url, siteName, dto.getFlywheelName());
            return url;
        } catch (Exception e) {
            throw new RuntimeException("文件上传失败: " + e.getMessage(), e);
        }
    }

    /**
     *  判断minio是否存在桶
     * @param bucketName
     */
    @SneakyThrows
    private void bucketExists(String bucketName) {
        boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        if (!bucketExists){
//                如果不存在，就创建桶
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 删除 文件
     * @param url
     */
    public void deleteFile(String url) {
        //        将传递的url 进行切割，获取到相对于桶的文件名
        String objectUrl = url.split(minioProperties.getBuckets().get("site").getName()+"/")[1];
        filesService.deleteFile(url);
        try {
            minioClient.removeObject(RemoveObjectArgs.builder()
                    .bucket(minioProperties.getBuckets().get("site").getName())
                    .object(objectUrl)
                    .build());

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(url+"文件删除失败");
        }
    }

    /**
     *    获取 minio 文件存储 url
     */
    public String getFileUrl(TableDto dto) {
      return filesService.getFileUrl(dto.getSiteName(),dto.getFlywheelName());
    }

    /**
     *  // 从 minio 下载 文件 到 本地
     * @param dto
     * @throws Exception
     */
    public  byte[] downloadFile(TableDto dto) throws Exception{
        String fileName = buildFileName(dto.getSiteName(), dto.getMatrixName(), dto.getFlywheelName());

        try (InputStream stream = minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(minioProperties.getBuckets().get("site").getName())
                        .object(fileName)
                        .build()
        )) {

            // 将输入流读取为字节数组
            byte[] fileBytes = StreamUtils.copyToByteArray(stream);

            return  fileBytes;

        } catch (Exception e) {
            log.error("文件下载失败: {}", fileName, e);
            throw new RuntimeException("文件下载失败: " + fileName, e);
        }
    }

    // 构造 获取 站点 文件路径 + 站点文件名称
    // C:\Users\dell\Desktop\Display.RT1000HMI
    public String buildFileName(String siteName,String matrixName ,String flywheelName) {
        String fileName = (flywheelName == null || flywheelName.isEmpty())
                ? siteName+"/"+siteName + FileTypeConstants.RT1000_FILE_TYPE
                : siteName+"/"+matrixName+"/"+flywheelName + FileTypeConstants.RT1000_FILE_TYPE;
        return  fileName;
    }

    public CommonResult uploadSvgFile(MultipartFile file, String type, String name) {
        // 判断当前文件是否存在
        // 1.存在则返回url
        // 2.不存在则创建文件
        try {
            // 确保存储桶存在
            bucketExists(minioProperties.getBuckets().get("images").getName());
            // 文件名
            String fileName = type+"/"+name+".svg";
            long fileSize = file.getSize();
            String contentType = file.getContentType();
            InputStream inputStream = file.getInputStream();
            if (contentType == null) {
                contentType = "application/octet-stream";
            }

            // 上传文件到MinIO
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(minioProperties.getBuckets().get("images").getName())
                    .object(fileName)
                    .stream(inputStream, fileSize, -1)
                    .contentType(contentType)
                    .build());
            // 关闭输入流
            if (inputStream != null) {
                inputStream.close();
            }
            String url = minioProperties.getUrl() +"/"+minioProperties.getBuckets().get("images").getName()+ "/" + fileName;
            return CommonResult.success(url);
        } catch (Exception e) {
            throw new RuntimeException("文件上传失败: " + e.getMessage(), e);
        }
    }

    public List<SvgVo> getAllSvgUrl() throws Exception {
        List<SvgVo> list = new ArrayList<>();
        String bucket = minioProperties.getBuckets().get("images").getName();

        Iterable<Result<Item>> items = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(bucket).recursive(true).build());

        for (Result<Item> result : items) {
            Item item = result.get();
            if (!item.isDir()) {
                String path = item.objectName();
                // 解析路径: type/name.svg
                String[] parts = path.split("/");
                if (parts.length == 2) {
                    String type = parts[0];
                    String name = parts[1].replace(".svg", "");

                    SvgVo vo = new SvgVo();
                    vo.setType(type);
                    vo.setName(name);
                    vo.setUrl(minioProperties.getUrl() + "/" + bucket + "/" + path);
                    list.add(vo);
                }
            }
        }
        return list;
    }

    public CommonResult uploadImage(MultipartFile file) {
        try {
            // 确保存储桶存在
            bucketExists(minioProperties.getBuckets().get("images").getName());
            // 文件名
            String contentType = file.getContentType();
//            String originalFilename = file.getOriginalFilename();
//            String extension = getExtensionFromFilename(originalFilename);
//            if (extension == null || extension.isEmpty()) {
//                return CommonResult.error("无法获取文件扩展名");
//            }
            String fileName = ImageName+"."+"png";
            long fileSize = file.getSize();
            InputStream inputStream = file.getInputStream();
            if (contentType == null) {
                contentType = "application/octet-stream";
            }

            // 上传文件到MinIO
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(minioProperties.getBuckets().get("images").getName())
                    .object(fileName)
                    .stream(inputStream, fileSize, -1)
                    .contentType(contentType)
                    .build());
            // 关闭输入流
            if (inputStream != null) {
                inputStream.close();
            }
            String url = minioProperties.getUrl() +"/"+minioProperties.getBuckets().get("images").getName()+ "/" + fileName;
            return CommonResult.success(url);
        } catch (Exception e) {
            throw new RuntimeException("文件上传失败: " + e.getMessage(), e);
        }
    }

    public String getImageUrl() {
        return minioProperties.getUrl() +"/"+minioProperties.getBuckets().get("images").getName()+ "/" + ImageName+".png";
    }
}
